package ext

inline fun Byte.toInt8() = this.toInt() and 0xFF

inline fun ByteArray.arg(index: Int) = this[index + 2].toInt8()

inline fun ByteArray.byteArg(index: Int) = this[index + 2].toInt8()

inline fun ByteArray.int16Arg(index: Int) = (this[index + 2].toInt8() shl 7) + this[index + 3].toInt8()

inline fun ByteArray.int32Arg(index: Int): Int {
    return (this[index + 2].toInt8() shl 21) +
            (this[index + 3].toInt8() shl 14) +
            (this[index + 4].toInt8() shl 7) +
            (this[index + 5].toInt8())
}

inline fun ByteArray.action() = this[2].toInt8()

inline fun ByteArray.int(index: Int) = this[index].toInt8()

inline fun Int.isMaskSet(bits: Int) = this and (0x01 shl bits) != 0x00

inline fun Int.isMaskClr(bits: Int) = this and (0x01 shl bits) == 0x00

inline fun Int.bitFieldValue(begin: Int, size: Int): Int {
    return (this shr begin) and ((0x01 shl size) - 1)
}

fun ByteArray.toHexString(): String {
    val sb = StringBuilder()
    this.forEach {
        sb.append(String.format("%02x ", it.toInt8()))
    }
    return sb.toString()
}

fun ByteArray.isChecked(): Boolean {
    if (this[1].toInt8() != size) {
        return false
    }
    var c = 0

    val len = size - 2

    for (i in 3 until len) {
        c = c xor this[i].toInt8()
    }

    return c == this[len].toInt8()
}

fun ByteArray.toMacAddress(): String {
    val sb = StringBuilder()
    this.forEachIndexed { index, byte ->
        if (index == (size - 1)) {
            sb.append(String.format("%02x", byte.toInt8()))
        } else {
            sb.append(String.format("%02x:", byte.toInt8()))
        }
    }
    return sb.toString()
}

fun ByteArray.subArray(index: Int, size: Int): ByteArray {
    val bytes = ByteArray(size)
    System.arraycopy(this, index, bytes, 0, size)
    return bytes
}

fun Byte.crc(initValue: Int): Int {
    var value = initValue
    var self = this.toInt8()
    for (i in 0 until 8) {
        if (0 != ((self xor value) and 0x01)) {
            value = value shr 1
            value = value xor 0xA001
        } else {
            value = value shr 1
        }
        self = self shr 1
    }
    return value
}

fun ByteArray.calcCrc(): Int {
    var value = 0
    this.forEach {
        value = it.crc(value)
    }
    return value
}
